#include "stdafx.h"
#include "PdfBookmark.h"

PdfBookmark::ChildrenWalker::~ChildrenWalker()
{

}


PdfBookmark::PdfBookmark(FPDF_DOCUMENT document)
	: type_(BOOKMARK_ROOT)
	, document_(document)
{
	FindChildren(document, nullptr);
}

PdfBookmark::PdfBookmark(FPDF_DOCUMENT document, FPDF_BOOKMARK fbookmark)
	: type_(BOOKMARK_INVALID)
	, document_(document)
{
	Init(document, fbookmark);
	FindChildren(document, fbookmark);
}

PdfBookmark::~PdfBookmark()
{
	for (auto child : children_) {
		delete child;
	}
}

void PdfBookmark::Init(FPDF_DOCUMENT document, FPDF_BOOKMARK fbookmark)
{
	unsigned long buffer_size = FPDFBookmark_GetTitle(fbookmark, nullptr, 0);
	if (buffer_size > 0) {
		title_.resize(buffer_size / 2);
		FPDFBookmark_GetTitle(fbookmark, (void*)title_.data(), buffer_size);
	}

	FPDF_DEST dest = FPDFBookmark_GetDest(document, fbookmark);
	if (dest) {
		page_index_ = FPDFDest_GetDestPageIndex(document, dest);
		type_ = BOOKMARK_PAGE;
	}
	else {
		FPDF_ACTION action = FPDFBookmark_GetAction(fbookmark);
		buffer_size = FPDFAction_GetURIPath(document, action, nullptr, 0);
		if (buffer_size > 0) {
			uri_.resize(buffer_size);
			FPDFAction_GetURIPath(document, action, (void*)uri_.data(), buffer_size);
		}
		type_ = BOOKMARK_URI;
	}
}

PdfBookmark::TYPE PdfBookmark::type() const
{
	return type_;
}

int PdfBookmark::GetPageIndex()
{
	if (type_ == BOOKMARK_PAGE)
	{
		return page_index_;
	}
	return -1;
}

int PdfBookmark::GetChildrenSize()
{
	return children_.size();
}


void PdfBookmark::AppenChild(PdfBookmark* child)
{
	children_.push_back(child);
}

void PdfBookmark::Accept(ChildrenWalker* walker)
{
	for (auto child : children_) {
		walker->Walk(this, child);
		child->Accept(walker);
	}
}

void PdfBookmark::FindChildren(FPDF_DOCUMENT document, FPDF_BOOKMARK fbookmark)
{
	FPDF_BOOKMARK child_bookmark = FPDFBookmark_GetFirstChild(document, fbookmark);
	while (child_bookmark) {
		AppenChild(new PdfBookmark(document, child_bookmark));
		child_bookmark = FPDFBookmark_GetNextSibling(document, child_bookmark);
	}
}
